package com.drakulo.games.ais.core.tech;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.drakulo.games.ais.core.GameData;
import com.drakulo.games.ais.core.Resource;

/**
 * Helper for technologies management
 * 
 * @author Drakulo
 * 
 */
public final class TechnologyHelper {
	private TechnologyHelper() {
		// Prevents instanciation
	}

	/**
	 * Create the basic technology tree
	 * 
	 * @return a list of all technologies linked with each other
	 */
	public static List<Technology> createTree() {
		// Static instanciation for now
		// TODO store those informations in a config file
		List<Technology> technologies = new ArrayList<Technology>();
		technologies.addAll(createEnergyTree());
		technologies.addAll(createCristalTree());
		technologies.addAll(createGasTree());
		technologies.addAll(createFoodTree());

		return technologies;
	}

	private static List<Technology> createEnergyTree() {
		List<Technology> technologies = new ArrayList<Technology>();

		Technology sp2 = create(0, "Solar Plant 2", false, "SOLAR_PLANT",
				"Gives better production of energy");
		sp2.setCost(initCost(500, 0, 0, 0));
		technologies.add(sp2);

		Technology rp = create(0, "Robot production", false, "WAREHOUSE",
				"Enable Robot Factory construction");
		rp.setCost(initCost(1500, 0, 0, 0));
		link(sp2, rp);
		technologies.add(rp);

		Technology sp3 = create(0, "Solar Plant 3", false, "SOLAR_PLANT",
				"Gives better production of energy");
		sp3.setCost(initCost(4000, 0, 0, 0));
		link(sp2, sp3);
		technologies.add(sp3);

		Technology arp = create(0, "Adv. Robot production", false, "WAREHOUSE",
				"Robot production goes faster");
		arp.setCost(initCost(7000, 0, 0, 0));
		link(rp, arp);
		technologies.add(arp);

		return technologies;
	}

	private static List<Technology> createCristalTree() {
		List<Technology> technologies = new ArrayList<Technology>();

		Technology cm2 = create(0, "Cristal Mining 2", false, "CRISTAL_MINE",
				"Gives better production of cristal");
		cm2.setCost(initCost(500, 0, 0, 0));
		technologies.add(cm2);

		Technology cm3 = create(0, "Cristal Mining 3", false, "CRISTAL_MINE",
				"Gives better production of cristal");
		cm3.setCost(initCost(4000, 0, 0, 0));
		link(cm2, cm3);
		technologies.add(cm3);

		return technologies;
	}

	private static List<Technology> createGasTree() {
		List<Technology> technologies = new ArrayList<Technology>();

		Technology gr2 = create(0, "Gas Refining 2", false, "GAS_REFINERY",
				"Gives better production of gas");
		gr2.setCost(initCost(500, 0, 0, 0));
		technologies.add(gr2);

		Technology gr3 = create(0, "Gas Refining 3", false, "GAS_REFINERY",
				"Gives better production of gas");
		gr3.setCost(initCost(4000, 0, 0, 0));
		link(gr2, gr3);
		technologies.add(gr3);

		return technologies;
	}

	private static List<Technology> createFoodTree() {
		List<Technology> technologies = new ArrayList<Technology>();

		Technology f2 = create(0, "Food Prod. 2", false, "BIO_FARM",
				"Gives better production of food");
		f2.setCost(initCost(500, 0, 0, 0));
		technologies.add(f2);

		Technology f3 = create(0, "Food Prod. 3", false, "BIO_FARM",
				"Gives better production of food");
		f3.setCost(initCost(4000, 0, 0, 0));
		link(f2, f3);
		technologies.add(f3);

		return technologies;
	}

	private static Technology create(int id, String name, boolean owned,
			String imageRef, String description) {
		Technology t = new Technology();
		// t.setId(id);
		t.setName(name);
		t.setOwned(owned);
		t.setImageKey(imageRef);
		t.setDescription(description);
		return t;
	}

	/**
	 * Link a parent technology and a child technology for bi directionnal link
	 * 
	 * @param parent
	 *            The parent technology
	 * @param child
	 *            The child technology
	 */
	private static void link(Technology parent, Technology child) {
		child.addParent(parent);
		parent.addChild(child);
	}

	/**
	 * THis method looks in the GameData technologies and returns root
	 * technologies : techs without parents
	 * 
	 * @return the root technologies
	 */
	public static List<Technology> getRootTechnologies() {
		// TODO cache this list for optimization
		List<Technology> roots = new ArrayList<Technology>();

		List<Technology> all = GameData.getTechnologies();
		for (Technology t : all) {
			if (t.getParents().isEmpty()) {
				roots.add(t);
			}
		}
		return roots;
	}

	private static Map<Resource, BigDecimal> initCost(int e, int c, int f, int g) {
		Map<Resource, BigDecimal> cost = new HashMap<Resource, BigDecimal>();
		cost.put(Resource.ENERGY, BigDecimal.valueOf(e));
		cost.put(Resource.CRISTAL, BigDecimal.valueOf(c));
		cost.put(Resource.FOOD, BigDecimal.valueOf(f));
		cost.put(Resource.GAS, BigDecimal.valueOf(g));
		return cost;
	}

	/**
	 * Tests if a list of technologies is totally owned
	 * 
	 * @param technologies
	 *            The list of technology names to test
	 * @return true if all technologies are owned
	 */
	public static boolean technologiesAreOwned(List<String> names) {
		for (String t : names) {
			if (!GameData.getTechnologyMap().get(t).isOwned()) {
				return false;
			}
		}
		return true;
	}
}
